package com.yugao.fintech.antelope.base.config.core;

import com.alibaba.fastjson2.JSON;
import com.yugao.fintech.antelope.base.config.model.ActionTypeEnum;
import com.yugao.fintech.antelope.base.model.enums.ConfigKeyEnum;
import com.yugao.fintech.antelope.base.model.module.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.Objects;

@Slf4j
@Component
public class RemoteConfigEventListener implements ApplicationListener<RemoteConfigEvent> {
    @Autowired
    private ConfigFactory configFactory;
    @Autowired
    private ScanConfigListener scanConfigListener;
    @Autowired
    private ThreadPoolTaskExecutor myThreadPoolTaskExecutor;

    @Override
    public void onApplicationEvent(@NotNull RemoteConfigEvent remoteConfigEvent) {
        // 这里采用异步线程, 避免 TenantContextHolder.clear() 影响发送者的tenantId传递,
        // 比如在system调用更新配置接口后, 由于配置采用bus广播到所有节点, 但是发布节点也会被广播到且不走消息队列, 直接走本地消息发布与监听
        // 因此这里不采用异步线程会导致请求线程的tenantId被清空
        myThreadPoolTaskExecutor.execute(() -> {
            try {
                Object source = remoteConfigEvent.getSource();
                String message = remoteConfigEvent.getMessage();
                log.info("刷新配置数据, message: {}", message);
                ConfigMsg payload = JSON.parseObject(message, ConfigMsg.class);
                if (Objects.nonNull(payload)) {
                    TenantContextHolder.get().setTenantId(payload.getTenantId());
                }
                if (payload.getActionType() == ActionTypeEnum.DELETE) {
                    configFactory.deleteConfig(ConfigKeyEnum.ofAndCheck(payload.getConfigKey()));
                } else {
                    configFactory.refreshConfig(payload);
                }
                scanConfigListener.execListener(payload);
            } finally {
                TenantContextHolder.clear();
            }
        });
    }
}